﻿using System;
using System.Collections.Generic;
using System.Text;

using Weazel.Badger.Vhdl.Expressions;
using Weazel.Badger.Vhdl.Statements;
using Weazel.Badger.Vhdl.Types;

namespace Weazel.Willows.InterfaceGeneration
{
	public abstract class MemoryMappedItem
	{
		private MemoryMap memoryMap;
		internal MemoryMap MemoryMap
		{
			get { return memoryMap; }
		}

		private int relativeBaseAddress;
		public int RelativeBaseAddress
		{
			get { return relativeBaseAddress; }
		}

		private int addressCount;
		public int AddressCount
		{
			get { return addressCount; }
		}

		public void AssignMemoryAddress(int baseAddress, int count)
		{
			this.relativeBaseAddress = baseAddress;
			this.addressCount = count;

			this.memoryMap.Assign(this, baseAddress, count);
		}

		public MemoryMappedItem(MemoryMap memoryMap)
		{
			this.memoryMap = memoryMap;
		}

		/// <summary>
		/// Given the number of chip selects (addresses in the addressspace) 
		/// and a relative address this method will return a string that can
		/// be used within a vhdl-case (switch) statement. eg. input 4 and 2
		/// will return "0010"
		/// </summary>
		/// <param name="relativeAddress"></param>
		/// <returns></returns>
		public string GetRelativeAddressAsPositionalString(int relativeAddress)
		{
			StringBuilder str = new StringBuilder();
			for (int i = 0; i < memoryMap.AddressesNeeded; i++)
				str.Append('0');
			str.Replace('0', '1', relativeAddress, 1);
			str.Insert(0, "\"");
			str.Append("\"");

			return str.ToString();
		}

		protected Expression GetChoiceExpression(StatementCollection collection, string choiceValue)
		{
			Expression choiceExpression =
				new Weazel.Badger.Vhdl.Expressions.ConstantExpression(
					collection, 
					choiceValue, 
					new StdLogicVector(memoryMap.AddressesNeeded), 
					null
				);

			return choiceExpression;
		}

		public abstract void SetupReadProcessCase(UserLogicEntity entity);
		public abstract void SetupWriteProcessCase(UserLogicEntity entity);		
	}
}
